#ifndef DEVICE
#define DEVICE

#include "Engine/EngineConfig.hpp"
#include "Engine/Renderer/Renderer.hpp"
#include "Input.hpp"
#include "SceneManager.hpp"
#include "Window.hpp"

namespace red{
	class Text;

	/// \brief Most important part of the Engine
	/// Keep all the stuff currently happening in it (SceneManager/Renderer/etc)
	class REDAPI Device{
	public:
		Device();
		~Device();

		/// \brief Initialize the Device
		void Init();

		/// \brief Step the Device. This must be executed every frame
		/// \return: False if the Device wants to stop the application
		bool Run();

		/// \brief Beginning of current frame rendering, Call it before any OpenGL Draw
		void BeginRender();

		/// \brief End of current frame rendering, Call it after ALL OpenGL & SFML Draw
		void EndRender();

		/// \brief Returns the device's OpenGL rendererer
		Renderer& GetRenderer() { return mRenderer; }

		/// \brief Returns the device's main Window
		Window& GetWindow() { return mWindow; }

		/// \brief Returns the device's inputs
		Input& GetInputs() { return mInputs; }

		/// \brief Returns the device's SceneManager
		SceneManager& GetSceneManager() { return mScene; }

		/// \brief Returns the device's main Clock ElapsedTime
		f32 GetFrameTime() const { return mFrameTime; }

		/// \brief Returns the FPS Text
		Text* GetFPSText() const { return mFPSText; }

		/// \brief Show or not the FPS Counter
		void ShowFps(bool pVal);

	private:
		/// \brief Event callback function. Process one event at a time
		/// \param pEvent : Event to process
		/// \return : false if user close window or press 'Escape', Default Behavior
		bool ProcessEvent(sf::Event &pEvent);

		/// \brief Instant Input Handling function, called every frame
		void HandleInputs();


		

		/// Window used for rendering
		Window mWindow;

		/// Main Inputs/Events
		Input mInputs;

		/// OpenGL Renderer
		Renderer mRenderer;

		/// Scene
		SceneManager mScene;

		/// Main Timer (Reset every frame)
		Clock mDeviceClock;
		f32 mFrameTime;

		/// FPS Counter Clock
		Clock mFPSClock;
		Text* mFPSText;

		/// Current time when Device is Initialised
		f32 mDeviceStartTime;	

		bool mInitialized;
	};
}
#endif